﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;
using Adalbertus.BudgetPlanner.Domain;
using Adalbertus.BudgetPlanner.Services;
using Caliburn.Micro;

namespace Adalbertus.BudgetPlanner.ViewModels.ExpenseTypes
{
    public class ExpenseTypesViewModel : Screen
    {
        private readonly ICashFlowService _cashFlowService;
        public ExpenseTypesViewModel(ICashFlowService cashFlowService)
        {
            Contract.Requires<ArgumentNullException>(cashFlowService != null);

            _cashFlowService = cashFlowService;
            _expenseTypes = new BindableCollection<ExpenseTypeVM>();
        }

        private BindableCollection<ExpenseTypeVM> _expenseTypes;
        public BindableCollection<ExpenseTypeVM> ExpenseTypes
        {
            get
            {
                Contract.Ensures(Contract.Result<BindableCollection<ExpenseTypeVM>>() != null);
                return _expenseTypes;
            }
        }

        private string _newExpenseTypeName;
        public string NewExpenseTypeName
        {
            get { return _newExpenseTypeName; }
            set
            {
                _newExpenseTypeName = value;
                NotifyOfPropertyChange(() => NewExpenseTypeName);
                NotifyOfPropertyChange(() => CanAddNewExpenseType);
            }
        }

        private string _newExpenseTypeDescription;
        public string NewExpenseTypeDescription
        {
            get { return _newExpenseTypeDescription; }
            set
            {
                _newExpenseTypeDescription = value;
                NotifyOfPropertyChange(() => NewExpenseTypeDescription);
            }
        }

        public bool CanAddNewExpenseType
        {
            get
            {
                return !string.IsNullOrWhiteSpace(NewExpenseTypeName);
            }
        }

        public void AddNewExpenseType()
        {
            CashFlow flowType = new CashFlow
                                    {
                                        Name = NewExpenseTypeName,
                                        Description = NewExpenseTypeDescription
                                    };
            ExpenseTypeVM expenseType = new ExpenseTypeVM(_cashFlowService.Create(NewExpenseTypeName, NewExpenseTypeDescription));
            ExpenseTypes.Add(expenseType);

            expenseType.PropertyChanged += ExpenseTypePropertyChanged;

            NewExpenseTypeName = string.Empty;
            NewExpenseTypeDescription = string.Empty;
        }

        public bool CanDeleteExpenseType(ExpenseTypeVM expenseType)
        {
            return !expenseType.IsReadOnly;
        }

        public void DeleteExpenseType(ExpenseTypeVM expenseType)
        {
            Contract.Requires<ArgumentNullException>(expenseType != null);

            ExpenseTypes.Remove(expenseType);
            expenseType.PropertyChanged -= ExpenseTypePropertyChanged;
            _cashFlowService.Remove(expenseType.WrappedCashFlow);
        }

        protected override void OnActivate()
        {
            base.OnActivate();
            LoadData();
        }

        private void LoadData()
        {
            foreach (ExpenseTypeVM expenseType in ExpenseTypes)
            {
                expenseType.PropertyChanged -= ExpenseTypePropertyChanged;
            }
            ExpenseTypes.Clear();
            IList<ExpenseTypeVM> expenseTypes =
                _cashFlowService.GetAll().Select(x => new ExpenseTypeVM(x)).ToList();

            ExpenseTypes.AddRange(expenseTypes);
            foreach (ExpenseTypeVM expenseType in expenseTypes)
            {
                expenseType.PropertyChanged += ExpenseTypePropertyChanged;
            }
        }

        private void ExpenseTypePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            ExpenseTypeVM expenseType = sender as ExpenseTypeVM;
            switch (e.PropertyName)
            {
                case "Name":
                case "Description":
                    _cashFlowService.Save(expenseType.WrappedCashFlow);
                    break;
            }
        }
    }
}
